home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 10
/
FM Towns Free Software Collection 10.iso
/
ms_dos
/
lib
/
happysrc
/
pcexpres.c
< prev
next >
Wrap
Text File
|
1994-11-14
|
37KB
|
916 lines
/************************************************************/
/* */
/* *** HAPPy Pascal Compiler *** */
/* 式のコンパイル処理 */
/* void expression(Set fsys) ; */
/* */
/* Copyright (c) H.Asano 1992,1994. */
/* */
/************************************************************/
#define EXTERN extern
#include "pascomp.h"
#include "pcpcd.h"
extern void gen0(enum pcdmnc) ;
extern void genp(enum pcdmnc,int) ;
extern void gen0t(enum pcdmnc,stp*) ;
extern void gen1t(enum pcdmnc,stp*,int) ;
extern void gen2t(enum pcdmnc,stp*,int,int) ;
extern void gencompare(enum pcdmnc,char,int) ;
extern void genldc(char,long) ;
extern void genixa(long,int) ;
extern void genchk(stp*,int,long,long) ;
extern void convertint(stp*) ;
extern void load(void) ;
extern void loadaddress(void) ;
extern ctp *searchsection(ctp*) ;
extern ctp *searchid(Set) ;
extern void insymbol(void) ;
extern void pcerr(int,char*);
extern char *inttoch(long) ;
extern void skip(Set) ;
extern boolean string(stp*) ;
extern boolean compatible(stp*,stp*) ;
extern void getbounds(stp*,long*,long*) ;
extern int align(stp*,int) ;
extern void conststrings(stp**, union valu*) ;
extern Set *mkset(Set*,int,...) ;
extern Set *orset(Set*,Set*) ;
extern void call(Set,ctp*) ;
extern void *Malloc(int) ;
static void array(Set) ;
static void recordmember(void) ;
static void ptr(void) ;
static void factident(Set) ;
static void factconst(Set) ;
static void factlparent(Set) ;
static void factnot(Set) ;
static void factset(Set) ;
static void factset2(Set,stp*,long*,boolean*,boolean*) ;
static void factnil(void) ;
static void simpleexpression(Set) ;
static void plusminusope(attr,enum operator) ;
static void orope(attr) ;
static void mulope(attr) ;
static void rdivope(attr) ;
static void inope(attr) ;
static void relope(attr,enum operator) ;
static void cnvfloat(attr*) ;
/*******************************************/
/* expression() : 式のコンパイル処理メイン */
/*******************************************/
void expression(Set fsys)
{
attr lattr ;
enum operator lop ;
Set ws ;
ws = fsys ;
addset(ws,relop) ;
simpleexpression(ws) ;
if(sy == relop) { /* 関係演算子の時 */
if(gattr.typtr)
if(gattr.typtr->form <= power) /* スカラ、範囲型、集合型の時 */
load() ; /* load命令 */
else loadaddress() ; /* それ以外は間接参照 */
lattr = gattr ; /* 今の式の属性を退避 */
lop = op ; /* 今の演算子を退避 */
if(lop == inop) /* in の時 integerでなければ */
if(gattr.typtr && (gattr.typtr->form == scalar) &&
(gattr.typtr != realptr)) /* inの前の式が順序型の時 */
convertint(gattr.typtr) ; /* 必要ならord命令生成 */
insymbol() ;
simpleexpression(fsys) ; /* 関係演算子の次の単純式の処理*/
if(gattr.typtr)
if(gattr.typtr->form <= power) /* スカラ、範囲型、集合型の時 */
load() ; /* load命令 */
else loadaddress() ; /* それ以外は間接参照 */
if((lattr.typtr) && (gattr.typtr))
if(lop == inop) inope(lattr) ; /* in 演算子処理 */
else {
if(lattr.typtr != gattr.typtr)
cnvfloat(&lattr) ; /* realへの変換処理 */
if(compatible(lattr.typtr,gattr.typtr)) /* 両方の型が同じ */
relope(lattr,lop) ; /* 関係演算子の処理 */
else pcerr(143,"") ; /* 演算子の両端の型が不一致 */
}
gattr.typtr = boolptr ;
gattr.kind = expr ; /* これ以降論理型の式とする */
}
}
/**************************************/
/* inope() : in 演算子処理 */
/**************************************/
static void inope(attr fattr)
{
if(gattr.typtr->form == power) /* 今の型が集合型 */
if(compatible(fattr.typtr,gattr.typtr->sf.pw.elset))
/* 底基の型と等しいか */
gen0(iINN) ; /* inn命令を生成 */
else {
pcerr(143,"") ; /* 演算子の両端の型が不一致*/
gattr.typtr = nil ;
}
else {
pcerr(130,"") ; /* 式は集合型でない */
gattr.typtr = nil ;
}
}
/*****************************************/
/* relope() : in 以外の関係演算子処理 */
/* = < > <> <= >= */
/*****************************************/
static void relope(attr fattr,enum operator fop)
{
int lsize ; /* 比較する大きさ */
char typind ; /* 比較命令の型 */
enum pcdmnc pcd ; /* 生成P-code */
lsize = fattr.typtr->size ; /* その型の大きさ */
switch(fattr.typtr->form) { /* 型で振り分ける */
case scalar : /* スカラー */
if(fattr.typtr == realptr) typind = 'r' ; /* real */
else if(fattr.typtr == boolptr) typind = 'b' ; /* boolean */
else if(fattr.typtr == charptr) typind = 'c' ; /* char */
else typind = 'i' ; /* integer/列挙型*/
break ;
case pointer : /* ポインタ型 */
if((fop != eqop) && (fop != neop)) /* = <> 以外 */
pcerr(131,"") ; /* 等しいかどうかの判定しか駄目*/
typind = 'a' ;
break ;
case power : /* 集合型 */
if((fop == ltop) || (fop == gtop)) /* < > の時 */
pcerr(132,"") ; /* 完全包含の判定は駄目 */
typind = 's' ;
break ;
case arrays : /* 配列型 */
if(! string(fattr.typtr)) /* 文字列でない時 */
pcerr(134,"") ; /* 演算対象の型に誤り */
typind = 'm' ;
break ;
case records : /* レコード型 */
pcerr(134,"") ; /* レコード型は駄目 */
typind = 'm' ;
break ;
case files : /* ファイル型 */
pcerr(133,"") ; /* ファイルの比較は駄目 */
typind = 'f' ;
}
switch(fop) { /* 演算子で生成命令を区別 */
case ltop : pcd = iLES ; break ; /* < les命令 */
case leop : pcd = iLEQ ; break ; /* <= leq命令 */
case gtop : pcd = iGRT ; break ; /* > grt命令 */
case geop : pcd = iGEQ ; break ; /* >= geq命令 */
case neop : pcd = iNEQ ; break ; /* <> neq命令 */
case eqop : pcd = iEQU ; /* = neq命令 */
}
gencompare(pcd,typind,lsize) ; /* 命令生成 */
}
/**************************************/
/* cnvfloat() : realへの変換処理 */
/**************************************/
static void cnvfloat(attr *fattr)
{
if((*fattr).typtr == intptr) { /* 前の式がinteger */
gen0(iFLO) ; /* 前の式を realに変換 */
(*fattr).typtr = realptr ;
} ;
if(gattr.typtr == intptr) { /* 今の式integer */
gen0(iFLT) ; /* 今の式をrealに変換 */
gattr.typtr = realptr ;
}
}
/***************************************/
/* selector() : 変数の属性を選択する */
/* α[・・・] : 配列変数 */
/* α^ : ポインタ変数 */
/* α. : レコード変数 */
/***************************************/
void selector(Set fsys, ctp *fcp)
{
Set ws ;
gattr.typtr = fcp->idtype ; /* 型を設定 */
gattr.kind = varbl ; /* 種類は 変数 */
switch(fcp->klass) { /* 変数の型で振り分ける */
case vars : /*[変数] */
if(fcp->n.v.vkind == actual) { /* 実変数 */
gattr.access = drct ;
gattr.vlevel = fcp->n.v.vlev ;
gattr.dplmt = fcp->n.v.vaddr;
}
else { /* formal (変数引数) */
if(gattr.typtr->form != files) /* ファイル型はlodaを生成しない */
gen2t(iLOD,nilptr,level-fcp->n.v.vlev,fcp->n.v.vaddr) ;
gattr.access = indrct ;
gattr.idplmt = 0 ;
gattr.vlevel = fcp->n.v.vlev ; /* ファイルが変数引数の時の */
gattr.dplmt = fcp->n.v.vaddr; /* ために退避しておく */
} /* 本当はこのやり方は違反です */
break ;
case field : /* レコードのフィールド */
/* with文配下しかこないはず */
if(display[disx].occur == crec){/* 固定フィールドの時 */
gattr.access = drct ;
gattr.vlevel = display[disx].clev ;
gattr.dplmt = display[disx].cdspl+ fcp->n.fldaddr ;
}
else { /* vrec(可変フィールドの時) */
if(level == 1) /* 大域変数 */
gen1t(iLDO,nilptr,display[disx].vdspl) ; /* ldo命令 */
else gen2t(iLOD,nilptr,0,display[disx].vdspl) ; /* lod命令 */
gattr.access = indrct ;
gattr.idplmt = fcp->n.fldaddr ;
}
break;
case func : /* 関数 */
gattr.access = drct ;
gattr.vlevel = fcp->n.pf.sd.d.pflev + 1 ;
gattr.dplmt = 0 ;
}
ws = selectsys ;
orset(&ws,&fsys) ;
if(! inset(ws,sy)) {
pcerr(59,"") ; /* 変数に誤りがある */
skip(ws) ; /* fsys+selectsysまで読み飛ばし*/
}
while(inset(selectsys,sy)) { /* [ . ^ の間処理する */
if(sy == lbrack) /* [ の時 */
array(fsys) ; /* 配列の処理 */
else if(sy == period) /* . の時 */
recordmember() ; /* レコードの各要素の処理 */
else /* ^ の時 */
ptr() ; /* ポインタの処理 */
if(! inset(ws,sy)) {
pcerr(6,"") ; /* 不当な記号が現れた */
skip(ws) ;
}
}
}
/*****************************************/
/* recordmember() : レコードの要素の処理 */
/*****************************************/
static void recordmember(void)
{
ctp *lcp ;
if(gattr.typtr)
if(gattr.typtr->form != records) {
pcerr(140,"") ; /* 変数の型がレコード型でない */
gattr.typtr = nil ; /* 今後のエラー防止のためnilにする*/
}
insymbol() ; /* 次のsymbol */
if(sy == ident) { /* 名前 */
if(gattr.typtr) { /* レコードの要素から名前を探す*/
lcp = searchsection(gattr.typtr->sf.re.fstfld) ;
if(!lcp) { /* 名前がない時 */
pcerr(152,id) ; /* レコードの欄ではない */
gattr.typtr = nil ; /* 今後のエラー防止のためnilにする*/
}
else { /* 名前がレコードの欄の時 */
gattr.typtr = lcp->idtype ; /* 名前の型 */
if(gattr.access==drct) /* 直接参照の時 */
gattr.dplmt += lcp->n.fldaddr ;
else /* 間接参照の時(indrct) */
gattr.idplmt += lcp->n.fldaddr ;
}
} /* end (typtr != nil) */
insymbol() ; /* 名前の次を読み込む */
}
else pcerr(2,"") ; /* 名前がない */
}
/*****************************************/
/* array() : 配列の処理 */
/*****************************************/
static void array(Set fsys)
{
attr lattr ; /* 1つ前の属性 */
long lmin,lmax ;
int lsize ;
int incsize ;
Set ws ;
do { /* 多次元配列のための繰り返し */
lattr = gattr ;
if(lattr.typtr)
if(lattr.typtr->form != arrays) {
pcerr(138,"") ; /* 変数の型は配列でない */
lattr.typtr = nil ;
gattr.typtr = nil ; /* loadaddressをさせない */
}
loadaddress() ;
insymbol() ;
mkset(&ws, comma,rbrack, -1) ;
orset(&ws, &fsys) ;
expression(ws) ; /* 添え字の式の処理 */
if(gattr.typtr) {
if(gattr.typtr->form != scalar)
pcerr(113,"") ; /* 添え字の型はスカラか範囲型 */
lsize = lattr.typtr->sf.ar.aeltype->size ;
lsize = align(gattr.typtr,lsize) ; /* 境界合わせ */
}
if(lattr.typtr) {
if(compatible(lattr.typtr->sf.ar.inxtype,
gattr.typtr)) { /* 添え字の型と等しい */
if(lattr.typtr->sf.ar.inxtype) {
getbounds(lattr.typtr->sf.ar.inxtype,&lmin,&lmax);
if(gattr.typtr)
if(gattr.kind == cst) { /* 添え字が定数の時 */
if((lmin<=gattr.cval.ival) && (gattr.cval.ival<=lmax)) {
incsize = (int)(gattr.cval.ival-lmin)*lsize ; /* 増分量 */
if(incsize) gen1t(iINC,nilptr,incsize);
}
else pcerr(148,"") ; /* 添え字の定数が範囲内にない */
}
else { /* 添え字が式の時 */
load() ; /* 添え字式をload */
convertint(gattr.typtr) ; /* 必要ならord命令生成 */
if(debug) genchk(intptr,1,lmin,lmax) ; /* chk命令生成 */
genixa(lmin,lsize) ; /* lxa命令の生成 */
}
}
}
else pcerr(139,"") ; /* 添え字の型が宣言と一致しない*/
gattr.typtr = lattr.typtr->sf.ar.aeltype ; /* 要素の型 */
gattr.kind = varbl ;
gattr.access = indrct ;
gattr.idplmt = 0 ;
}
} while(sy == comma) ;
if(sy == rbrack) insymbol() ;
else pcerr(12,"") ; /* ] がない */
}
/*******************************************/
/* ptr() : ポインタ参照,バッファ変数の処理 */
/*******************************************/
static void ptr(void)
{
if(gattr.typtr)
if(gattr.typtr->form == pointer) { /* ポインタ型の時 */
load() ;
gattr.typtr = gattr.typtr->sf.pt.eltype ; /* 指し示すものの型 */
if(debug) /* デバッグコンパイルの時 */
gen0(iCKA) ; /* CKA命令 */
gattr.kind = varbl ;
gattr.access = indrct ; /* 間接参照 */
gattr.idplmt = 0 ;
}
else if(gattr.typtr->form == files){/* ファイル型の時 */
if(gattr.access == indrct) /* ファイル変数が変数引数の時 */
gen2t(iLOD,nilptr,level-gattr.vlevel,gattr.dplmt) ;
gattr.typtr = gattr.typtr->sf.fi.filtype ; /* ファイルの基の型 */
}
else pcerr(141,"") ; /* ファイル型か指標型でない */
insymbol() ;
}
/**************************************/
/* factor() : 式の因子(factor)の処理 */
/**************************************/
static void factor(Set fsys)
{
Set ws ;
if(! inset(facbegsys,sy)) {
pcerr(58,"") ; /* 項に誤りがある */
ws = fsys ;
orset(&ws, &facbegsys) ;
skip(ws) ; /* fsys+factbegsysまで読み飛ばし*/
gattr.typtr = nil ;
}
while(inset(facbegsys,sy)) {
switch(sy) {
case ident : /* 名前の時 */
factident(fsys) ;
break ;
case intconst : /* 整数定数 */
case realconst : /* 実数定数 */
case stringconst : /* 文字列 */
factconst(fsys) ;
break ;
case lparent : /* ( */
factlparent(fsys) ;
break ;
case notsy : /* not */
factnot(fsys) ;
break ;
case lbrack : /* [ 集合の始まり記号 */
factset(fsys) ;
break ;
case nilsy : /* nil */
factnil() ;
break ;
}
if(! inset(fsys,sy)) {
pcerr(6,"") ; /* 不当な記号が現れた */
skip(ws) ; /* fsys+factbegsysまで読み飛ばし*/
}
}
}
/**************************************/
/* factident() : 名前因子の処理 */
/**************************************/
static void factident(Set fsys)
{
ctp *lcp ;
Set ws ;
mkset(&ws, konst,vars,field,func,-1) ; /* 名前を、定数・変数・フィールド・ */
lcp = searchid(ws) ; /* 関数の中から探す */
insymbol() ;
if(lcp->klass == func) {
call(fsys,lcp) ; /* 関数の時、関数呼び出し */
gattr.kind = expr ;
if(gattr.typtr)
if(gattr.typtr->form == subrange) /* 範囲型の時 */
gattr.typtr = gattr.typtr->sf.su.rangetype ; /* 基の型 */
}
else if(lcp->klass == konst) { /* 定数の時 */
gattr.typtr = lcp->idtype ;
gattr.kind = cst ;
gattr.cval = lcp->n.values ; /* 値を入れる */
}
else { /* 変数、レコードフィールドの時*/
selector(fsys,lcp) ; /* 属性選択 */
if(gattr.typtr)
if(gattr.typtr->form == subrange) /* 範囲型の時 */
gattr.typtr = gattr.typtr->sf.su.rangetype ; /* 基の型 */
}
}
/**************************************/
/* factconst() : 定数因子の処理 */
/**************************************/
static void factconst(Set fsys)
{
stp *lsp,*lsp1 ;
gattr.kind = cst ;
switch(sy) {
case intconst : /* 整数定数 */
gattr.typtr = intptr ;
gattr.cval = val ; /* 値を設定 */
break ;
case realconst : /* 実数定数 */
gattr.typtr = realptr ;
gattr.cval = val ;
break ;
case stringconst : /* 文字列 */
conststrings(&(gattr.typtr),&(gattr.cval));/*文字列定数の処理 */
}
insymbol() ;
}
/**************************************/
/* factlparent() : (~)の処理 */
/**************************************/
static void factlparent(Set fsys)
{
Set ws ;
insymbol() ;
ws = fsys ;
addset(ws,rparent) ;
expression(ws) ; /* )が出てくるまで式の処理 */
if(sy == rparent) insymbol() ;
else pcerr(4,"") ; /* ) がない */
}
/**************************************/
/* factnot() : not の処理 */
/**************************************/
static void factnot(Set fsys)
{
insymbol() ;
factor(fsys) ; /* notの次の因子の解析 */
load() ; /* load命令の出力 */
if(gattr.typtr != boolptr) {
pcerr(135,"not") ; /* 論理型でないといけない */
gattr.typtr = nil ; /* 次のエラーをださないためnil*/
}
gen0(iNOT) ; /* not命令の出力 */
}
/**************************************/
/* factset() : 集合の処理 */
/**************************************/
static void factset(Set fsys)
{
stp *lsp ;
csp *lvp ;
long csetpart; /* 集合の定数要素パート */
boolean varpart ; /* 変数要素がある時 true */
boolean cstpart ; /* 定数要素がある時 true */
boolean test ;
Set ws ;
insymbol() ;
csetpart= 0 ; /* 固定要素集合のクリア */
varpart = false ;
cstpart = false ;
lsp = (stp*)Malloc(sizeof(stp)) ; /* 集合の型を作成 */
lsp->form = power ;
lsp->size = setsize ;
lsp->assignflag = true ;
lsp->sf.pw.packed = both ;
lsp->sf.pw.elset = nil ;
lsp->sf.pw.elmin = setlow ;
lsp->sf.pw.elmax = sethigh ;
if(sy == rbrack) { /* 空集合の時 */
gattr.typtr = lsp ;
gattr.kind = cst ;
insymbol() ;
}
else { /* 要素がある時 */
do {
mkset(&ws,comma,rbrack,period2,-1);
orset(&ws,&fsys) ;
expression(ws) ; /* 要素 */
if(gattr.typtr)
if((gattr.typtr->form != scalar)/* 要素が順序型かチェック */
|| (gattr.typtr == realptr)) {
pcerr(136,"") ; /* 要素記述は順序型のこと */
gattr.typtr = nil ;
}
else {
if(!lsp->sf.pw.elset) /* 集合の型がない時 */
lsp->sf.pw.elset = gattr.typtr ;/* 要素の型を集合の型とする */
if(compatible(lsp->sf.pw.elset,gattr.typtr)){ /* 要素の型 */
if(sy == period2)
factset2(fsys,lsp,&csetpart,&cstpart,&varpart);/* ..の処理 */
else { /* 通常の集合要素の処理 */
if(gattr.kind == cst) /* 要素が定数 */
if((gattr.cval.ival < (long)lsp->sf.pw.elmin) || /* 集合の*/
(gattr.cval.ival > (long)lsp->sf.pw.elmax)) /* 範囲 */
pcerr(607,inttoch((long)lsp->sf.pw.elmax)) ;/* 範囲内にない*/
else {
csetpart |=(1L << gattr.cval.ival);/* 集合の定数要素を加える*/
cstpart = true ;
}
else { /* 要素が変数の時 */
load() ; /* 要素値をload */
convertint(gattr.typtr) ; /* 必要ならord命令生成 */
if(debug)
genchk(intptr,111, /* 式がHAPPyの集合範囲に入るか*/
(long)lsp->sf.pw.elmin,(long)lsp->sf.pw.elmax) ;
/* 集合要素の範囲チェック */
gen0(iSGS) ; /* sgs命令(要素1個の集合作成) */
if(varpart) gen0(iUNI) ; /* uni命令(変数の集合に加える)*/
else varpart = true ; /* 初めて変数が現れた時 trueに*/
}
}
}
else pcerr(137,"") ; /* 集合の要素の型が不一致 */
}
if(test=(sy==comma)) insymbol(); /* , なら次の要素を読む */
} while(test) ; /* , ならば次の要素の処理 */
if(sy == rbrack) insymbol() ; /* ] ならば次のsymbolを読む */
else pcerr(12,"") ; /* ] がない */
gattr.typtr = lsp ; /* 集合の型を入れる */
}
lvp = (csp*)Malloc(sizeof(csp)) ; /* 集合定数のエリア確保 */
lvp->cclass = pset ;
lvp->c.pval = csetpart ;
gattr.cval.valp = lvp ;
if(varpart && cstpart) { /* 変数要素と定数要素両方あり */
genldc('s',(long)nil) ; /* ldcs命令 */
gen0(iUNI) ; /* uni命令 */
gattr.kind = expr ;
}
}
/****************************************/
/* loadelement() : 集合の 範囲要素load*/
/****************************************/
static void loadelement(stp *fsp,boolean *varpart,int kind)
{
int pope ; /* mms命令の p オペランド
0 下限 上限 チェックなし
1 下限 上限 チェックあり
2 上限 下限 チェックなし
3 上限 下限 チェックあり */
/* debugオプション指定時に chk命令以外でチェックさせるのは
このmms命令のみ。統一がとれていないけど、暫定的にこのようにした*/
pope = kind + (int)(debug) ;
load() ; /* 要素式をload */
convertint(gattr.typtr) ; /* 必要ならord命令生成 */
genp(iMMS,pope) ; /* mms命令生成 */
if(*varpart) gen0(iUNI) ; /* uni命令(変数の集合に加える)*/
else *varpart = true ;
}
/****************************************/
/* factset2() : 集合の 範囲要素の処理 */
/* 順序式..順序式 */
/****************************************/
static void factset2(Set fsys,stp *fsp,
long *csetpart,boolean *cstpart,boolean *varpart)
{
attr lattr,lattr2 ;
short m ;
Set ws ;
lattr = gattr ;
if(gattr.kind != cst) { /* 定数以外 ・・・ 式 */
load() ; /* 要素式をload */
convertint(gattr.typtr) ; /* 必要ならord命令生成 */
insymbol() ; /* 次の要素を読む */
mkset(&ws,comma,rbrack,-1);
orset(&ws,&fsys);
expression(ws) ; /* 次の要素の処理 */
if(gattr.typtr)
if(compatible(gattr.typtr,lattr.typtr))/* 前の要素との型チェック*/
loadelement(fsp,varpart,0) ; /* 上限式load&mms */
else pcerr(137,"") ; /* 集合の要素の型が不一致 */
}
else { /* 最初の要素が定数の時 */
insymbol() ; /* 次の要素を読む */
mkset(&ws,comma,rbrack,-1);
orset(&ws,&fsys);
expression(ws) ; /* 次の要素の処理 */
if(gattr.typtr)
if(compatible(gattr.typtr,lattr.typtr)) {/* 前の要素との型チェック*/
if(gattr.kind == cst) { /* 上限値が定数 */
if(lattr.cval.ival <= gattr.cval.ival) /*上限値の方が大きい*/
if((lattr.cval.ival >= (long)fsp->sf.pw.elmin) &&/* 要素の範囲*/
(gattr.cval.ival <= (long)fsp->sf.pw.elmax)){ /* チェック*/
for(m=(short)lattr.cval.ival;m<=(short)gattr.cval.ival;m++)
*csetpart |=(1L << m); /* 集合の定数要素を加える */
*cstpart = true ;
}
else
pcerr(607,inttoch((long)fsp->sf.pw.elmax)) ;/* 範囲内にない*/
}
else { /* 定数..式 */
load() ; /* 上限式をload */
convertint(gattr.typtr) ; /* 必要ならord命令生成 */
gattr = lattr ;
loadelement(fsp,varpart,2) ; /* 下限定数load&mms */
}
}
else pcerr(137,"") ; /* 集合の要素の型が不一致 */
}
}
/**************************************/
/* factnil() : nil の処理 */
/**************************************/
static void factnil(void)
{
gattr.typtr = nilptr ; /* nil 型 */
gattr.kind = cst ;
gattr.cval.ival = 0 ;
insymbol() ;
}
/**************************************/
/* term() : 式の項(term)の処理 */
/**************************************/
static void term(Set fsys)
{
attr lattr ; /* 1つ前の項の属性 */
enum operator lop ; /* 1つ前の演算子 */
Set ws ;
ws = fsys ;
addset(ws,mulop) ;
factor(ws) ; /* 因子の処理 */
while(sy == mulop) { /* * / div mod and の時 */
load() ; /* 今の項をload */
lattr = gattr ; /* 今の項の属性を退避 */
lop = op ; /* 今の演算子を退避 */
insymbol() ;
factor(ws) ; /* 次の項の処理 */
load() ; /* その項をload */
if((lattr.typtr) && (gattr.typtr))
switch(lop) { /* 演算子で振り分ける */
case mul : mulope(lattr) ; /* * 演算子処理 */
break ;
case rdiv : rdivope(lattr) ; /* / 演算子処理 */
break ;
case idiv : /* div 演算子 */
case imod : /* mod 演算子 */
if((lattr.typtr == intptr) &&
(gattr.typtr == intptr)) /* div/mod の対象はinteger */
(lop==idiv) ? gen0(iDVI) : gen0(iMOD);/*dvi / mod命令を生成*/
else {
pcerr(134,"") ; /* 演算対象の型に誤り */
gattr.typtr = nil ;
}
break ;
case andop : /* and 演算子 */
if((lattr.typtr == boolptr) &&
(gattr.typtr == boolptr)) /* and の対象はboolean */
gen0(iAND) ; /* and命令を生成 */
else {
pcerr(135,"and") ; /* 論理型でない */
gattr.typtr = nil ;
}
}
else gattr.typtr = nil ;
}
}
/**************************************/
/* mulope() : * 演算子処理 */
/**************************************/
static void mulope(attr fattr)
{
if((fattr.typtr == intptr) && /* * の両端がinteger */
(gattr.typtr == intptr))
gen0(iMPI) ; /* mpi命令の生成 */
else {
cnvfloat(&fattr) ; /* realへの変換処理 */
if((fattr.typtr == realptr) &&
(gattr.typtr == realptr)) /* 両端ともrealになっていれば */
gen0(iMPR) ; /* mpr命令を生成 */
else if((gattr.typtr->form == power) /* 集合型で */
&& compatible(fattr.typtr,gattr.typtr)) { /* 型が適合する */
if(fattr.typtr->sf.pw.packed != both) /* 前の式の詰めあり/なし*/
gattr.typtr->sf.pw.packed = fattr.typtr->sf.pw.packed ;
gen0(iINT) ; /* int命令を生成 */
}
else { /* 型が適合しない */
pcerr(134,"") ; /* 演算対象の型に誤り */
gattr.typtr = nil;
}
}
}
/**************************************/
/* rdivope() : / 演算子処理 */
/**************************************/
static void rdivope(attr fattr)
{
cnvfloat(&fattr) ; /* realへの変換処理 */
if((fattr.typtr == realptr) &&
(gattr.typtr == realptr)) /* 両端ともrealになっていれば */
gen0(iDVR) ; /* dvr命令を生成 */
else {
pcerr(134,"") ; /* 演算対象の型に誤り */
gattr.typtr = nil ;
}
}
/*********************************************/
/* simpleexpression() : 単純式の処理 */
/*********************************************/
static void simpleexpression(Set fsys)
{
boolean sign = false ;
boolean neg ;
attr lattr ;
enum operator lop ;
Set ws ;
sign = (op==plus) || (op==minus) ; /* + か - の時 真 */
if(sign) {
neg = (op == minus) ; /* - の時 true */
insymbol() ;
}
ws = fsys ;
addset(ws,addop) ;
term(ws) ; /* 項の処理 */
if(sign) { /* + - がついていた時 */
if(gattr.typtr==intptr) {
if(neg)
if(gattr.kind==cst) /* 定数の時は 値を反転する */
gattr.cval.ival = -gattr.cval.ival ;
else { /* 変数の時 */
load() ;
gen0(iNGI) ; /* ngi 命令の出力 */
}
}
else if(gattr.typtr==realptr) { /* 実数は定数でもngr命令 */
if(neg) {
load() ;
gen0(iNGR) ; /* ngr 命令の出力 */
}
}
else { /* 整数、実数以外に符号がついている*/
pcerr(134,"") ; /* 演算対象の型に誤り */
gattr.typtr = nil ; /* 今後のためにnilとする */
}
}
while(sy ==addop) {
load() ;
lattr = gattr ; /* 今の属性を退避 */
lop = op ; /* 今の演算子を退避 */
insymbol() ;
term(ws) ; /* 項の処理 */
if((lattr.typtr) && (gattr.typtr))
switch(lop) { /* 前の演算子で振り分ける */
case plus :
case minus : plusminusope(lattr,lop);
break ; /* + - の演算子処理 */
case orop : load() ;
orope(lattr) ; /* or 演算子処理 */
break ;
}
else gattr.typtr = nil ;
}
}
/**************************************/
/* plusminusope() : + - 演算子処理 */
/**************************************/
static void plusminusope(attr fattr,enum operator fop)
{
if((fattr.typtr == intptr) && /* 前と今の式が両方ともinteger*/
(gattr.typtr == intptr)) /* であれば */
if((gattr.kind == cst) &&
(gattr.cval.ival <= 32767)) {
(fop == plus)
? gen1t(iINC,intptr,(int)gattr.cval.ival)
: gen1t(iDEC,intptr,(int)gattr.cval.ival) ;
gattr.kind = expr ;
}
else {
load() ;
(fop == plus) ? gen0(iADI) : gen0(iSBI) ; /* adi/sbi命令を生成 */
}
else {
load() ;
cnvfloat(&fattr) ; /* realに変換 */
if((fattr.typtr == realptr) && /* 前と今の式が両方ともreal */
(gattr.typtr == realptr)) /* になっていれば */
(fop == plus) ? gen0(iADR) : gen0(iSBR) ; /* adr/sbr命令を生成 */
else if((fattr.typtr->form == power) /* 前の式が集合型で */
&& compatible(fattr.typtr,gattr.typtr)){/* 基底の型が同じ */
if(fattr.typtr->sf.pw.packed != both) /* 前の式の詰めあり/なし*/
gattr.typtr->sf.pw.packed = fattr.typtr->sf.pw.packed ;
load() ;
(fop == plus) ? gen0(iUNI) : gen0(iDIF) ; /* uni/dif命令を生成 */
}
else { /* 型が適合しない */
pcerr(134,"") ; /* 演算対象の型に誤り */
gattr.typtr = nil;
}
}
}
/**************************************/
/* orope() : or 演算子処理 */
/**************************************/
static void orope(attr fattr)
{
if((fattr.typtr == boolptr) && /* 前と今の式が両方ともboolean*/
(gattr.typtr == boolptr)) /* であれば */
gen0(iIOR) ; /* ior命令を生成 */
else {
pcerr(135,"or") ; /* 演算対象は論理型でないと駄目*/
gattr.typtr = nil ;
}
}